#include "XmlParser.h"

/**
 * XML Tokens
 */
static const QString c_XmlToken_Panel("EpsilonPanel");
static const QString c_XmlToken_Equipment("EpsilonEquipmentItem");
static const QString c_XmlToken_Info("EpsilonInfoItem");
static const QString c_XmlToken_RemoteID("remoteId");
static const QString c_XmlToken_InitialValue("initial-value");
static const QString c_XmlToken_Access("permission");
static const QString c_XmlToken_PanelID("panelId");
static const QString c_XmlToken_Poll("poll");

static const QString c_True("true");
static const QString c_False("false");

XmlParser::XmlParser() :
    m_PanelDataList(),
    m_PanelIDs(),
    m_CurrentPanelIndex(-1),
    m_Xml()
{
}

void XmlParser::ParseFile(QFile& rFile)
{
    if (!rFile.isOpen())
    {
        return;
    }

    Reset_();
    m_Xml.setDevice(&rFile);

    while(!m_Xml.atEnd() && !m_Xml.hasError())
    {
        m_Xml.readNext();

        if(m_Xml.tokenType() == QXmlStreamReader::StartDocument)
        {
            continue;
        }

        ParsePanel_();
    }
}

void XmlParser::Reset_()
{
    m_PanelDataList.clear();
    m_PanelIDs.clear();
    m_CurrentPanelIndex = -1;
}

void XmlParser::ParsePanel_()
{
    if((m_Xml.tokenType() == QXmlStreamReader::StartElement) &&
       (m_Xml.name() == c_XmlToken_Panel))
    {
        ++ m_CurrentPanelIndex;

        // Create a new QHash object and put it into the vector
        m_PanelDataList.append(PanelData_t());

        QXmlStreamAttributes Attributes = m_Xml.attributes();
        if(Attributes.hasAttribute(c_XmlToken_RemoteID))
        {
            QString PanelName = Attributes.value(c_XmlToken_PanelID).toString();
            m_PanelIDs.append(PanelName);
            QString GSOID = Attributes.value(c_XmlToken_RemoteID).toString();

            while(!(m_Xml.tokenType() == QXmlStreamReader::EndElement &&
                    m_Xml.name() == c_XmlToken_Panel))
            {
                m_Xml.readNext();

                if((m_Xml.tokenType() == QXmlStreamReader::StartElement) &&
                   (m_Xml.name() == c_XmlToken_Info))
                {
                    ParseInfoItem_(GSOID);
                }
                else if((m_Xml.tokenType() == QXmlStreamReader::StartElement) &&
                   (m_Xml.name() == c_XmlToken_Equipment))
                {
                    ParseEquipmentItem_();
                }
            }
        }
    }
}

void XmlParser::ParseEquipmentItem_()
{
    QXmlStreamAttributes Attributes = m_Xml.attributes();
    if(Attributes.hasAttribute(c_XmlToken_RemoteID))
    {
        QString GSOID = Attributes.value(c_XmlToken_RemoteID).toString();

        while(!(m_Xml.tokenType() == QXmlStreamReader::EndElement &&
                m_Xml.name() == c_XmlToken_Equipment))
        {
            m_Xml.readNext();

            if((m_Xml.tokenType() == QXmlStreamReader::StartElement) &&
               (m_Xml.name() == c_XmlToken_Info))
            {
                ParseInfoItem_(GSOID);
            }
            else if((m_Xml.tokenType() == QXmlStreamReader::StartElement) &&
               (m_Xml.name() == c_XmlToken_Equipment))
            {
                ParseEquipmentItem_();
            }
        }
    }
}

void XmlParser::ParseInfoItem_(const QString& GSOID)
{
    QXmlStreamAttributes Attributes = m_Xml.attributes();
    if(Attributes.hasAttribute(c_XmlToken_RemoteID))
    {
        QString AttributeID = Attributes.value(c_XmlToken_RemoteID).toString();
        QString InitialValue = Attributes.value(c_XmlToken_InitialValue).toString();
        QString Access = Attributes.value(c_XmlToken_Access).toString();
        QString Poll = Attributes.value(c_XmlToken_Poll).toString();

        if (Poll.compare(c_True, Qt::CaseInsensitive) != 0)
        {
            Poll = c_False;
        }

        /**
          * For a given Panel and a given GSOID put an Attribute ID and
          * its corresponding properties
          */
        m_PanelDataList[m_CurrentPanelIndex][GSOID].insert(
            AttributeID,
            AttributeProperties(InitialValue, Access, Poll));
    }
}
